<?php 

namespace common\service;

use common\libs\BlockChain;
use common\libs\Curl;
use common\model\sell66\BotInv;
use common\model\sell66\User;
use think\Config;

class ChainService
{
    private $blackChain = null;

    public static $instance = null;
	
	private function __construct(){
        $config = Config::get('blockwallet_config');
        $this->blackChain = new BlockChain();
        $this->blackChain->setPrivateKey($config['private_key']);
        $this->blackChain->setBot($config['bot']);
        $this->blackChain->setRequestUrl($config['request_url']);
        $this->blackChain->setCallBackWallet($config['callback_wallet']);
        $this->blackChain->setCallBackStatus($config['callback_status']);
        $this->blackChain->setRpcUrl($config['rpc_url']);
	}

	public static function getInstance(){
		if(self::$instance == null){
			self::$instance = new self();
		}
		return self::$instance;
	}

    public function assetList($userId)
    {
        $userInfo = User::with('usersteam')->find($userId);
        $params = [
            'wallet_address' => $userInfo['wallet_address'],
        ];
        $sign = $this->blackChain->getSign($params);
        $params['sign'] = $sign;
        $params = [
            'jsonrpc' => '2.0',
            'method' => 'asset_list',
            'params' => $params,
            'id' => 'get_asset_list',
        ];
        $result = Curl::http_post($this->blackChain->getRpcUrl(), json_encode($params));
        $result = json_decode($result, true);
        if(!empty($result['result'])){
            return $result['result'];
        }
        LogService::getInstance()->addActionLog(__FUNCTION__, $userId, 0, '请求钱包列表失败', $result);
        return false;
    }

	public function getIssueId($botInvId)
    {
        $botInvInfo = BotInv::find($botInvId);
        if(empty($botInvInfo)){
            return false;
        }
        $userId = $botInvInfo['user_id'];
        $userInfo = User::with('usersteam')->find($userId);
        $steamId = $userInfo['usersteam']['steam_id'];
        $params = [
            'appid' => $botInvInfo['app_id'],
            'oid' => $botInvInfo['o_id'],
            'classid' => $botInvInfo['class_id'],
            'instanceid' => $botInvInfo['instance_id'],
            'market_hash_name' => $botInvInfo['market_hash_name'],
            'market_name' => $botInvInfo['market_name'],
            'action_link' => $botInvInfo['action_link'],
            'owner_id' => $steamId,
            'to_address' => $userInfo['wallet_address'],
            'rarity_color' => $botInvInfo['rarity_color'],
            'callback' => $this->blackChain->getCallBackStatus(),
        ];
        $sign = $this->blackChain->getSign($params);
        $params['sign'] = $sign;
        $params = [
            'jsonrpc' => '2.0',
            'method' => 'asset_issue',
            'params' => $params,
            'id' => 'get_issue_id',
        ];

        $result = Curl::http_post($this->blackChain->getRpcUrl(), json_encode($params));
        $result = json_decode($result, true);
        if(!empty($result['result']['issue_id'])){
            $issueId= $result['result']['issue_id'];
            if(BotInv::updateBotInv(['bot_inv_id'=>$botInvId], ['status'=>BotInv::$statusMaps['issuing'], 'issue_id'=>$issueId, 'issue_status'=>BotInv::$issueStatusMaps['accepted']])){
                return true;
            }
        }
        LogService::getInstance()->addActionLog(__FUNCTION__, $userId, $steamId, '发行失败', $result);
        return false;
    }

    public function checkIssueStatus($botInvId)
    {
        $botInvInfo = BotInv::find($botInvId);
        if(empty($botInvInfo['issue_id'])){
            return false;
        }
        $issueId = $botInvInfo['issue_id'];

        $userId = $botInvInfo['user_id'];
        $userInfo = User::with('usersteam')->find($userId);
        $steamId = $userInfo['usersteam']['steam_id'];
        $params = [
            'issue_id' => $issueId,
        ];
        $sign = $this->blackChain->getSign($params);
        $params['sign'] = $sign;
        $params = [
            'jsonrpc' => '2.0',
            'method' => 'asset_issue_status',
            'params' => $params,
            'id' => 'check_issue_status',
        ];
        $result = Curl::http_post($this->blackChain->getRpcUrl(), json_encode($params));
        $result = json_decode($result, true);
        if(isset($result['result']['status'])){
            $issueStatus= $result['result']['status'];
            $AssetHash = !empty($result['result']['asset'])? $result['result']['asset']: '';

            $data = [
                'issue_status'=>$issueStatus, 
                'asset_hash'=>$AssetHash
            ];

            if ($issueStatus == BotInv::$issueStatusMaps['finish']) {
                $data['status'] = BotInv::$statusMaps['issued'];
            }

            if(BotInv::updateBotInv(['bot_inv_id'=>$botInvId], $data)){
                return true;
            }
        }
        LogService::getInstance()->addActionLog(__FUNCTION__, $userId, $steamId, '获取发行状态失败', $result);
        return false;
    }

    public function takeBack($userId, $botInvIds)
    {
        $botInvIds = explode(',', $botInvIds);
        if(!$botInvIds){
            return false;
        }
        $botInvList = BotInvService::getInstance()->checkTakeBackBotInvsByIds($userId, $botInvIds);
        if($botInvList == -1){
            return [-1, '物品不存在'];
        }
        if($botInvList == -2){
            return [-2, '不能销毁不属于你的物品'];
        }
        if($botInvList == -3){
            return [-3, '存在无法销毁的物品'];
        }
        $userInfo = User::with('usersteam')->find($userId);
        $assetHashArr = array_column($botInvList, 'asset_hash');
        $assetHashStr = implode($assetHashArr, ',');
        $params = [
            'wallet_address' => $userInfo['wallet_address'],
            'asset' => $assetHashStr
        ];
        $sign = $this->blackChain->getSign($params);
        $params['sign'] = $sign;
        $params = [
            'jsonrpc' => '2.0',
            'method' => 'asset_withdraw',
            'params' => $params,
            'id' => 'destroy_asset_hash',
        ];
        $result = Curl::http_post($this->blackChain->getRpcUrl(), json_encode($params));
        $result = json_decode($result, true);
        if(array_key_exists('result', $result) && $result['result'] === NULL){
            BotInv::updateWaitTakingInvs($userId, $botInvIds);
            return true;
        }
        LogService::getInstance()->addActionLog(__FUNCTION__, $userId, 0, '取回失败', $result);
        return false;
    }

    public function checkTakeBackStatus($botInvId)
    {
        $botInvInfo = BotInv::find($botInvId);
        if(empty($botInvInfo['asset_hash'])){
            return false;
        }
        $assetHash = $botInvInfo['asset_hash'];

        $params = [
            'asset' => $assetHash,
        ];
        $sign = $this->blackChain->getSign($params);
        $params['sign'] = $sign;
        $params = [
            'jsonrpc' => '2.0',
            'method' => 'asset_withdraw_status',
            'params' => $params,
            'id' => 'check_take_back_status',
        ];
        $result = Curl::http_post($this->blackChain->getRpcUrl(), json_encode($params));
        $result = json_decode($result, true);
        if(isset($result['result']['status'])){
            $takeStatus = $result['result']['status'];

            $data = array(
                'take_status' => $takeStatus,
            );

            if ($takeStatus == BotInv::$takeStatusMaps['finish']) {
                $data['issue_id'] = 0;
                $data['issue_status'] = -1;
                $data['take_status'] = -1;
                $data['status'] = BotInv::$statusMaps['default'];
            } elseif ($takeStatus == BotInv::$takeStatusMaps['cancel']) {
                $data['status'] = BotInv::$statusMaps['issued'];
            }

            if(BotInv::updateBotInv(['bot_inv_id'=>$botInvId], $data)){
                return true;
            }
        }
        LogService::getInstance()->addActionLog(__FUNCTION__, $botInvInfo['user_id'], 0, '获取取回状态失败', $result);
        return false;
    }

    public function notify()
    {
        $msg = file_get_contents("php://input");
        $msg = $this->check($msg);
        if(!$msg){
            return false;
        }
        $issueId = $msg['issue_id'];
        $issueStatus = $msg['status'];
        $AssetHash = $msg['asset'];

        $data = ['issue_status'=>$issueStatus, 'asset_hash'=>$AssetHash];
        if ($issueStatus == BotInv::$issueStatusMaps['finish']) {
            $data['status'] = BotInv::$statusMaps['issued'];
        }

        if(BotInv::updateBotInv(['issue_id'=>$issueId], $data)){
            return true;
        }
        return false;
    }

    public function check($msg = null)
    {
        $msg = base64_decode($msg);
        $msg = json_decode($msg, true);
        if(empty($msg) || empty($msg['sign']) || empty($msg['issue_id']) || empty($msg['status'])){
            return false;
        }

        $sign = $msg['sign'];
        unset($msg['sign']);

        if($this->blackChain->getSign($msg) != $sign){
            return false;
        }
        return $msg;
    }
}